home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 22 / Cream of the Crop 22.iso / math / ast53src.zip / WDRIVER.C < prev    next >
C/C++ Source or Header  |  1996-09-29  |  46KB  |  1,684 lines

  1. /*
  2. ** Astrolog (Version 5.30) File: wdriver.c
  3. **
  4. ** IMPORTANT NOTICE: The graphics database and chart display routines
  5. ** used in this program are Copyright (C) 1991-1996 by Walter D. Pullen
  6. ** (Astara@msn.com, http://www.magitech.com/~cruiser1/astrolog.htm).
  7. ** Permission is granted to freely use and distribute these routines
  8. ** provided one doesn't sell, restrict, or profit from them in any way.
  9. ** Modification is allowed provided these notices remain with any
  10. ** altered or edited versions of the program.
  11. **
  12. ** The main planetary calculation routines used in this program have
  13. ** been Copyrighted and the core of this program is basically a
  14. ** conversion to C of the routines created by James Neely as listed in
  15. ** Michael Erlewine's 'Manual of Computer Programming for Astrologers',
  16. ** available from Matrix Software. The copyright gives us permission to
  17. ** use the routines for personal use but not to sell them or profit from
  18. ** them in any way.
  19. **
  20. ** The PostScript code within the core graphics routines are programmed
  21. ** and Copyright (C) 1992-1993 by Brian D. Willoughby
  22. ** (brianw@sounds.wa.com). Conditions are identical to those above.
  23. **
  24. ** The extended accurate ephemeris databases and formulas are from the
  25. ** calculation routines in the program "Placalc" and are programmed and
  26. ** Copyright (C) 1989,1991,1993 by Astrodienst AG and Alois Treindl
  27. ** (alois@azur.ch). The use of that source code is subject to
  28. ** regulations made by Astrodienst Zurich, and the code is not in the
  29. ** public domain. This copyright notice must not be changed or removed
  30. ** by any user of this program.
  31. **
  32. ** Initial programming 8/28,30, 9/10,13,16,20,23, 10/3,6,7, 11/7,10,21/1991.
  33. ** X Window graphics initially programmed 10/23-29/1991.
  34. ** PostScript graphics initially programmed 11/29-30/1992.
  35. ** Last code change made 9/22/1996.
  36. */
  37.  
  38. #include "astrolog.h"
  39.  
  40.  
  41. #ifdef WIN
  42. /*
  43. ******************************************************************************
  44. ** Windows Command Processing.
  45. ******************************************************************************
  46. */
  47.  
  48. /* Process one command line switch passed to the program dealing with the   */
  49. /* Windows features. This is just like the processing of each switch in the */
  50. /* main program, however here each switch has been prefixed with an 'W'.    */
  51.  
  52. int NProcessSwitchesW(argc, argv, pos, fOr, fAnd, fNot)
  53. int argc, pos;
  54. bool fOr, fAnd, fNot;
  55. char **argv;
  56. {
  57.   int darg = 0, i;
  58.   char sz[cchSzDef], ch1;
  59.  
  60.   ch1 = argv[0][pos+1];
  61.   switch (argv[0][pos]) {
  62.   case chNull:
  63.     if (argc <= 1) {
  64.       ErrorArgc("W");
  65.       return tcError;
  66.     }
  67.     i = atoi(argv[1]);
  68.     PostMessage(wi.hwnd, WM_COMMAND, i, 0L);
  69.     darg++;
  70.     break;
  71.  
  72.   case 'N':
  73.     if (argc <= 1) {
  74.       ErrorArgc("WN");
  75.       return tcError;
  76.     }
  77.     i = atoi(argv[1]);
  78.     if (!FValidTimer(i)) {
  79.       ErrorValN("WN", i);
  80.       return tcError;
  81.     }
  82.     wi.nTimerDelay = i;
  83.     darg++;
  84.     break;
  85.  
  86.   case 'M':
  87.     if (argc <= 2) {
  88.       ErrorArgc("WM");
  89.       return tcError;
  90.     }
  91.     i = atoi(argv[1]);
  92.     if (!FValidMacro(i)) {
  93.       ErrorValN("WM", i);
  94.       return tcError;
  95.     }
  96.     i--;
  97.     sprintf(sz, "%s\t%sF%d", argv[2], i < 12 ? "" : (i < 24 ? "Shift+" :
  98.       (i < 36 ? "Ctrl+" : "Alt+")), i % 12 + 1);
  99.     ModifyMenu(wi.hmenu, (WORD)(cmdMacro01 + i), MF_BYCOMMAND | MF_STRING,
  100.       (WORD)(cmdMacro01 + i), sz);
  101.     darg += 2;
  102.     break;
  103.  
  104.   case 'n':
  105.     SwitchF(wi.fNoUpdate);
  106.     break;
  107.  
  108.   default:
  109.     ErrorSwitch(argv[0]);
  110.     return tcError;
  111.   }
  112.   /* 'darg' contains the value to be added to argc when we return. */
  113.   return darg;
  114. }
  115.  
  116.  
  117. /* Change the pixel size of the window so its internal drawable area is the */
  118. /* dimensions of the current graphics chart. Both the upper left and lower  */
  119. /* right corners of the window may change depending on the scroll position. */
  120.  
  121. void ResizeWindowToChart()
  122. {
  123.   RECT rcOld, rcNew;
  124.   int xScr, yScr;
  125.   HDC hdc;
  126.  
  127.   if (!us.fGraphics || gs.xWin == 0 || gs.yWin == 0)
  128.     return;
  129.   GetWindowRect(wi.hwnd, &rcOld);
  130.   hdc = GetDC(wi.hwnd);
  131.   xScr = GetDeviceCaps(hdc, HORZRES);
  132.   yScr = GetDeviceCaps(hdc, VERTRES);
  133.   ReleaseDC(wi.hwnd, hdc);
  134.   rcNew.left = rcOld.left + gi.xOffset;
  135.   rcNew.top  = rcOld.top + gi.yOffset;
  136.   rcNew.right = rcNew.left + gs.xWin + (gi.nMode == 0 ? SIDESIZE : 0) + 23;
  137.   rcNew.bottom = rcNew.top + gs.yWin + 61;
  138.   if (rcNew.right > xScr)
  139.     OffsetRect(&rcNew, xScr - rcNew.right, 0);
  140.   if (rcNew.bottom > yScr)
  141.     OffsetRect(&rcNew, 0, yScr - rcNew.bottom);
  142.   if (rcNew.left < 0)
  143.     OffsetRect(&rcNew, -rcNew.left, 0);
  144.   if (rcNew.top < 0)
  145.     OffsetRect(&rcNew, 0, -rcNew.top);
  146.   MoveWindow(wi.hwnd, rcNew.left, rcNew.top,
  147.     rcNew.right - rcNew.left, rcNew.bottom - rcNew.top, fTrue);
  148. }
  149.  
  150.  
  151. /* Given a relationship chart mode, return the menu command that sets it. */
  152.  
  153. WORD WCmdFromRc(int rc)
  154. {
  155.   switch (rc) {
  156.   case rcTriWheel: case rcQuadWheel: /* Fall through */
  157.   case rcDual:       return cmdRelComparison;
  158.   case rcSynastry:   return cmdRelSynastry;
  159.   case rcComposite:  return cmdRelComposite;
  160.   case rcMidpoint:   return cmdRelMidpoint;
  161.   case rcDifference: return cmdRelDate;
  162.   case rcBiorhythm:  return cmdRelBiorhythm;
  163.   case rcTransit:    return cmdRelTransit;
  164.   case rcProgress:   return cmdRelProgressed;
  165.   default:           return cmdRelNo;
  166.   }
  167. }
  168.  
  169.  
  170. /* Change relationship chart modes. Given a new mode, we put a check by its */
  171. /* menu command, and erase the check by the menu command for the old mode.  */
  172.  
  173. void SetRel(int rc)
  174. {
  175.   CheckMenu(WCmdFromRc(us.nRel), fFalse);
  176.   CheckMenu(WCmdFromRc(rc), fTrue);
  177.   us.nRel = rc;
  178.   wi.fCast = fTrue;
  179. }
  180.  
  181.  
  182. /* The main program, the starting point of Astrolog for Windows, follows.   */
  183. /* This is like the "main" function in standard C. The program initializes  */
  184. /* here, then spins in a tight message processing loop until it terminates. */
  185.  
  186. int PASCAL WinMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow)
  187. HANDLE hInstance;
  188. HANDLE hPrevInstance;
  189. LPSTR lpszCmdLine;
  190. int nCmdShow;
  191. {
  192.   MSG msg;
  193.   WNDCLASS wndclass;
  194. #ifdef BETA
  195.   char sz[cchSzMax];
  196. #endif
  197.  
  198.   /* Set up the window class shared by all instances of Astrolog. */
  199.  
  200.   wi.hinst = hInstance;
  201.   if (!hPrevInstance) {
  202.     ClearB((lpbyte)&wndclass, sizeof(WNDCLASS));
  203.     wndclass.style = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW;
  204.     wndclass.lpfnWndProc = WndProc;
  205.     wndclass.cbClsExtra = 0;
  206.     wndclass.cbWndExtra = 0;
  207.     wndclass.hInstance = wi.hinst;
  208.     wndclass.hIcon = LoadIcon(wi.hinst, MAKEINTRESOURCE(icon));
  209.     wndclass.hCursor = LoadCursor((HINSTANCE)NULL, IDC_ARROW);
  210.     wndclass.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  211.     wndclass.lpszMenuName = MAKEINTRESOURCE(menu);
  212.     wndclass.lpszClassName = szAppName;
  213.     if (!RegisterClass(&wndclass)) {
  214.       PrintError("The window class could not be registered.");
  215.       return -1L;
  216.     }
  217.   }
  218.  
  219.   /* Create the actual window to be used and drawn on by this instance. */
  220.  
  221.   wi.hmenu = LoadMenu(wi.hinst, MAKEINTRESOURCE(menu));
  222.   wi.hwndMain = CreateWindow(
  223.     szAppName,
  224.     "Astrolog 5.30",
  225.     WS_CAPTION |
  226.     WS_SYSMENU |
  227.     WS_MINIMIZEBOX |
  228.     WS_MAXIMIZEBOX |
  229.     WS_THICKFRAME |
  230.     WS_VSCROLL |
  231.     WS_HSCROLL |
  232.     WS_CLIPCHILDREN |
  233.     WS_OVERLAPPED,
  234.     CW_USEDEFAULT, 0,
  235.     CW_USEDEFAULT, 0,
  236.     (HWND)NULL,
  237.     wi.hmenu,
  238.     wi.hinst,
  239.     (LPSTR)NULL);
  240.   if (wi.hwndMain == (HWND)NULL) {
  241.     PrintError("The window could not be created.");
  242.     return -1L;
  243.   }
  244.  
  245.   /* Set up some globals that can't be initialized at compile time. */
  246.  
  247.   is.S = stdout;
  248.   ofn.hwndOwner = wi.hwndMain;
  249.   ofn.lpstrFile = szFileName;
  250.   ofn.lpstrFileTitle = szFileTitle;
  251.   prd.hwndOwner = wi.hwndMain;
  252.   wi.haccel = LoadAccelerators(wi.hinst, MAKEINTRESOURCE(accelerator));
  253.   wi.kiPen = gi.kiLite;
  254.  
  255.   /* Process the astrolog.dat file and the Windows command line. */
  256.  
  257.   FProcessSwitchFile(DEFAULT_INFOFILE, NULL);
  258.   FProcessCommandLine(lpszCmdLine);
  259.   ciTran = ciFour = ciThre = ciTwin = ciCore;
  260.  
  261.   /* Actually bring up and display the window for the first time. */
  262.  
  263.   ResizeWindowToChart();
  264.   ShowWindow(wi.hwndMain, nCmdShow);
  265.   RedoMenu();
  266.   wi.nTimer = SetTimer(wi.hwnd, 1, wi.nTimerDelay, NULL);
  267. #ifdef BETA
  268.   sprintf(sz, "This is a beta version of %s %s! "
  269.     "That means changes are still being made and testing is not complete. "
  270.     "If this is being run after %s %d, %d, "
  271.     "it should be replaced with the finished release.",
  272.     szAppName, szVersionCore, szMonth[ciSave.mon], ciSave.day, ciSave.yea);
  273.   PrintWarning(sz);
  274. #endif
  275.  
  276.   /* Process window messages until the program is told to terminate. */
  277.  
  278.   while (GetMessage(&msg, (HWND)NULL, 0, 0)) {
  279.     if (!TranslateAccelerator(wi.hwndMain, wi.haccel, &msg))
  280.       TranslateMessage(&msg);
  281.     DispatchMessage(&msg);
  282.   }
  283.  
  284.   /* Cleanup and exit Astrolog for Windows. */
  285.  
  286.   UnregisterClass(szAppName, wi.hinst);
  287.   return msg.wParam;
  288. }
  289.  
  290.  
  291. /* This is the main message processor for the Astrolog window. Given a */
  292. /* user input or other message, do the appropriate action and updates. */
  293.  
  294. LONG API WndProc(hwnd, wMsg, wParam, lParam)
  295. HWND hwnd;
  296. WORD wMsg;
  297. WORD wParam;
  298. LONG lParam;
  299. {
  300.   HDC hdc;
  301.   HPEN hpen, hpenOld;
  302.   HBRUSH hbr;
  303.   RECT rc;
  304.   int x, y;
  305.  
  306.   wi.hwnd = hwnd;
  307.   switch (wMsg) {
  308.  
  309.     /* A command, most likely a menu option, was given. */
  310.  
  311.     case WM_COMMAND:
  312.       switch (NWmCommand(wParam)) {
  313.       case 1:
  314.         goto LWM_CLOSE;
  315.       case -1:
  316.         return DefWindowProc(hwnd, wMsg, wParam, lParam);
  317.       default:
  318.         ProcessState();
  319.       }
  320.       break;
  321.  
  322.     /* When a part of a window is uncovered, Windows quickly blanks it out, */
  323.     /* usually with white, before having the app redraw that section. Most  */
  324.     /* apps don't do anything here, however Astrolog can quickly draw with  */
  325.     /* a more appropriate color since we know our chart's background color. */
  326.  
  327.     case WM_ERASEBKGND:
  328.       if (!(wi.fNoUpdate & 1)) {
  329.         GetClipBox((HDC)wParam, &rc);
  330.         hbr = CreateSolidBrush(rgbbmp[gs.fInverse ? kWhite : kBlack]);
  331.         FillRect((HDC)wParam, &rc, hbr);
  332.         DeleteObject(hbr);
  333.       }
  334.       return fTrue;
  335.  
  336.     /* The window was just created. Setup the scrollbars. */
  337.  
  338.     case WM_CREATE:
  339.       SetScrollRange(hwnd, SB_HORZ, 0, nScrollDiv, fFalse);
  340.       SetScrollRange(hwnd, SB_VERT, 0, nScrollDiv, fFalse);
  341.       break;
  342.  
  343.     /* The window has been resized. Change the chart size if need be. */
  344.  
  345.     case WM_SIZE:
  346.       wi.xClient = LOWORD(lParam);
  347.       wi.yClient = HIWORD(lParam);
  348.       if (wi.fWindowChart || wi.fChartWindow) {
  349.         gs.xWin = wi.xClient; gs.yWin = wi.yClient;
  350.       }
  351.       break;
  352.  
  353.     /* All or part of the window needs to be redrawn. Go do so. */
  354.  
  355.     case WM_PAINT:
  356.       if (!(wi.fNoUpdate & 1))
  357.         FRedraw();
  358.       break;
  359.  
  360.     /* The mouse has been left clicked or dragged over the window. */
  361.  
  362.     case WM_LBUTTONDOWN:
  363.     case WM_MOUSEMOVE:
  364.  
  365.       /* Treat dragging with the mouse down as a Shift+left click. */
  366.       if (wMsg == WM_MOUSEMOVE) {
  367.         if ((wParam & MK_LBUTTON) == 0 ||
  368.           (wParam & MK_SHIFT) || (wParam & MK_CONTROL))
  369.           break;
  370.         wParam = MK_SHIFT;
  371.       }
  372.       x = WLo(lParam);
  373.       y = WHi(lParam);
  374.  
  375.       /* Alt+click on a world map chart means relocate the chart there. */
  376.       if (wMsg == WM_LBUTTONDOWN && GetKeyState(VK_MENU) < 0) {
  377.         if (fMap && gs.nRot == 0 && !gs.fConstel && !gs.fMollewide) {
  378.           Lon = DegToDec(rDegHalf-(real)(x-gi.xOffset)/(real)gs.xWin*rDegMax);
  379.           if (Lon < -rDegHalf)
  380.             Lon = -rDegHalf;
  381.           else if (Lon > rDegHalf)
  382.             Lon = rDegHalf;
  383.           Lat = DegToDec(rDegQuad-(real)(y-gi.yOffset)/(real)gs.yWin*180.0);
  384.           if (Lat < -rDegQuad)
  385.             Lat = -rDegQuad;
  386.           else if (Lat > rDegQuad)
  387.             Lat = rDegQuad;
  388.           wi.xMouse = -1;
  389.           wi.fCast = fTrue;
  390.         }
  391.         break;
  392.       }
  393.       hdc = GetDC(hwnd);
  394.       hpen = CreatePen(PS_SOLID, 0, (COLORREF)rgbbmp[wi.kiPen]);
  395.       hpenOld = SelectObject(hdc, hpen);
  396.  
  397.       /* Ctrl+click means draw a rectangle. Ctrl+Shift+click does ellipse. */
  398.       if (wParam & MK_CONTROL) {
  399.         SelectObject(hdc, GetStockObject(NULL_BRUSH));
  400.         if (wParam & MK_SHIFT)
  401.           Ellipse(hdc, wi.xMouse, wi.yMouse, x, y);
  402.         else
  403.           Rectangle(hdc, wi.xMouse, wi.yMouse, x, y);
  404.  
  405.       /* Shift+click means draw a line from the last to current position. */
  406.       } else if (wParam & MK_SHIFT) {
  407.         if (wi.xMouse >= 0) {
  408.           MoveTo(hdc, wi.xMouse, wi.yMouse);
  409.           LineTo(hdc, x, y);
  410.           if (wMsg == WM_MOUSEMOVE) {
  411.             wi.xMouse = x; wi.yMouse = y;
  412.           }
  413.         }
  414.  
  415.       /* A simple click means set a pixel and remember that location. */
  416.       } else {
  417.         SetPixel(hdc, x, y, (COLORREF)rgbbmp[wi.kiPen]);
  418.         wi.xMouse = x; wi.yMouse = y;
  419.       }
  420.       SelectObject(hdc, hpenOld);
  421.       DeleteObject(hpen);
  422.       ReleaseDC(hwnd, hdc);
  423.       break;
  424.  
  425.     /* The mouse has been right clicked on the window. If on a world map  */
  426.     /* or astro-graph chart, relocate the chart to the mouse coordinates. */
  427.  
  428.     case WM_RBUTTONDOWN:
  429.       x = WLo(lParam);
  430.       y = WHi(lParam);
  431.       if (us.fGraphics && (us.fAstroGraph || gi.nMode == gWorldMap) &&
  432.         gs.nRot == 0 && !gs.fConstel && !gs.fMollewide) {
  433.         Lon = DegToDec(rDegHalf-(real)(x-gi.xOffset)/
  434.           (real)gs.xWin*rDegMax);
  435.         if (Lon < -rDegHalf)
  436.           Lon = -rDegHalf;
  437.         else if (Lon > rDegHalf)
  438.           Lon = rDegHalf;
  439.         Lat = DegToDec(rDegQuad-(real)(y-gi.yOffset)/
  440.           (real)gs.yWin*181.0);
  441.         if (Lat < -rDegQuad)
  442.           Lat = -rDegQuad;
  443.         else if (Lat > rDegQuad)
  444.           Lat = rDegQuad;
  445.         ciCore = ciMain;
  446.         wi.fCast = fTrue;
  447.         ProcessState();
  448.       }
  449.       break;
  450.  
  451.     /* A timer message is received at a defined regular interval. */
  452.  
  453.     case WM_TIMER:
  454.       if (!gs.nAnim || wi.fPause)
  455.         break;
  456.       Animate(gs.nAnim, wi.nDir);  /* Update chart if animation mode on. */
  457.       wi.fRedraw = fTrue;
  458.       ProcessState();
  459.       break;
  460.  
  461.     /* Define the minimum and maximum size the window may be resized to. */
  462.  
  463.     case WM_GETMINMAXINFO:
  464.       ((MINMAXINFO FAR *)lParam)->ptMinTrackSize.x = BITMAPX1;
  465.       ((MINMAXINFO FAR *)lParam)->ptMinTrackSize.y = BITMAPY1;
  466.       ((MINMAXINFO FAR *)lParam)->ptMaxTrackSize.x = BITMAPX;
  467.       ((MINMAXINFO FAR *)lParam)->ptMaxTrackSize.x = BITMAPY;
  468.       break;
  469.  
  470.     /* The horizontal scrollbar was clicked on or used in some way. */
  471.  
  472.     case WM_HSCROLL:
  473.       x = wi.xScroll;
  474.       switch (wParam) {
  475.       case SB_LINEUP:
  476.         wi.xScroll--;
  477.         break;
  478.       case SB_LINEDOWN:
  479.         wi.xScroll++;
  480.         break;
  481.       case SB_PAGEUP:
  482.         wi.xScroll -= nScrollPage;
  483.         break;
  484.       case SB_PAGEDOWN:
  485.         wi.xScroll += nScrollPage;
  486.         break;
  487.       case SB_THUMBPOSITION:
  488.         wi.xScroll = LOWORD(lParam);
  489.         break;
  490.       default:
  491.         return fFalse;
  492.       }
  493.       wi.xScroll = max(0, min(wi.xScroll, nScrollDiv));
  494.       if (wi.xScroll == x)
  495.         break;
  496.       SetScrollPos(hwnd, SB_HORZ, wi.xScroll, fTrue);
  497.       wi.fRedraw = fTrue;
  498.       ProcessState();
  499.       break;
  500.  
  501.     /* The vertical scrollbar was clicked on or used in some way. */
  502.  
  503.     case WM_VSCROLL:
  504.       y = wi.yScroll;
  505.       switch(wParam) {
  506.       case SB_LINEUP:
  507.         wi.yScroll--;
  508.         break;
  509.       case SB_LINEDOWN:
  510.         wi.yScroll++;
  511.         break;
  512.       case SB_PAGEUP:
  513.         wi.yScroll -= nScrollPage;
  514.         break;
  515.       case SB_PAGEDOWN:
  516.         wi.yScroll += nScrollPage;
  517.         break;
  518.       case SB_THUMBPOSITION:
  519.         wi.yScroll = LOWORD(lParam);
  520.         break;
  521.       default:
  522.         return fFalse;
  523.       }
  524.       wi.yScroll = max(0, min(wi.yScroll, nScrollDiv));
  525.       if (wi.yScroll == y)
  526.         break;
  527.       SetScrollPos(hwnd, SB_VERT, wi.yScroll, fTrue);
  528.       wi.fRedraw = fTrue;
  529.       ProcessState();
  530.       break;
  531.  
  532.     /* The window is being terminated. Clean up and free program data. */
  533.  
  534.     case WM_CLOSE:
  535. LWM_CLOSE:
  536.       if (us.fNoQuit) {
  537.         PrintWarning("Program exiting is not allowed now.");
  538.         break;
  539.       }
  540.       if (wi.hpen != (HPEN)NULL)
  541.         DeleteObject(wi.hpen);
  542.       if (wi.nTimer != 0)
  543.         KillTimer(hwnd, 1);
  544.       DestroyWindow(hwnd);
  545.       if (hwnd == wi.hwndMain)
  546.         PostQuitMessage(0);
  547.       break;
  548.  
  549.     /* Messages not processed here are handled by Windows in a default way. */
  550.  
  551.     default:
  552.       return DefWindowProc(hwnd, wMsg, wParam, lParam);
  553.     }
  554.   return fFalse;
  555. }
  556.  
  557.  
  558. /* This is called after some action has been done that probably changed the */
  559. /* chart state, such as a menu command was run. Update anything needing it. */
  560.  
  561. void ProcessState()
  562. {
  563.   if (wi.fMenuAll) {       /* Redetermine all menu checks if need be. */
  564.     RedoMenu();
  565.     wi.fMenu = fTrue;
  566.   }
  567.   if (wi.fMenu) {          /* Update menu if we added/removed check marks. */
  568.     DrawMenuBar(wi.hwnd);
  569.     wi.fMenu = fFalse;
  570.   }
  571.   if (wi.fCast)            /* Recasting a chart implies redrawing it too. */
  572.     wi.fRedraw = fTrue;
  573.  
  574.   /* If the chart type was changed, clear all the setting flags, then set */
  575.   /* the appropriate core switch settings based on the new chart type.    */
  576.  
  577.   if (wi.nMode) {
  578.     ClearB((lpbyte)&us.fListing,
  579.       (int)((lpbyte)&us.fVelocity - (lpbyte)&us.fListing));
  580.     ClearB((lpbyte)&us.fCredit,
  581.       (int)((lpbyte)&us.fLoop - (lpbyte)&us.fCredit));
  582.     us.nArabic = gi.nMode = 0;
  583.     switch (wi.nMode) {
  584.       case gBiorhythm:
  585.       case gWheel:      us.fListing    = fTrue; break;
  586.       case gHouse:      us.fWheel      = fTrue; break;
  587.       case gGrid:       us.fGrid       = fTrue; break;
  588.       case gHorizon: us.fHorizon = fTrue; us.fHorizonSearch = fFalse; break;
  589.       case gOrbit:      us.fOrbit      = fTrue; break;
  590.       case gSector:     us.fSector     = fTrue; break;
  591.       case gAstroGraph: us.fAstroGraph = fTrue; break;
  592.       case gEphemeris:  us.fEphemeris  = fTrue; break;
  593.       case gWorldMap:   gi.nMode = gWorldMap; break;
  594.       case gGlobe:      gi.nMode = gGlobe;    break;
  595.       case gPolar:      gi.nMode = gPolar;    break;
  596.       case gCalendar:   us.fCalendar   = fTrue; break;
  597.       case gDisposit:   us.fInfluence  = fTrue; break;
  598.       case gAspect:     us.fAspList    = fTrue; break;
  599.       case gMidpoint:   us.fMidpoint   = fTrue; break;
  600.       case gArabic:     us.nArabic     = 1; break;
  601.       case gSign:       us.fSign       = fTrue; break;
  602.       case gObject:     us.fObject     = fTrue; break;
  603.       case gHelpAsp:    us.fAspect     = fTrue; break;
  604.       case gConstel:    us.fConstel    = fTrue; break;
  605.       case gPlanet:     us.fOrbitData  = fTrue; break;
  606.       case gMeaning:    us.fMeaning    = fTrue; break;
  607.       case gSwitch:     us.fSwitch     = fTrue; break;
  608.       case gObscure:    us.fSwitchRare = fTrue; break;
  609.       case gKeystroke:  us.fKeyGraph   = fTrue; break;
  610.       case gCredit:     us.fCredit     = fTrue; break;
  611.       case gRising:     us.fHorizon = us.fHorizonSearch = fTrue; break;
  612.       case gTraTraHit:  us.fInDay      = fTrue; break;
  613.       case gTraTraInf:  us.fInDayInf   = fTrue; break;
  614.       case gTraNatHit:  us.fTransit    = fTrue; break;
  615.       case gTraNatInf:  us.fTransitInf = fTrue; break;
  616.     }
  617.     wi.nMode = 0;
  618.     wi.fRedraw = fTrue;
  619.   }
  620.   if (wi.fRedraw)    /* Send the window a redraw message if need be. */
  621.     RedrawWindow(wi.hwnd, NULL, (HRGN)NULL, RDW_INVALIDATE);
  622. }
  623.  
  624.  
  625. /* Given a command, process it, changing any appropriate program settings. */
  626. /* Return values are 0, meaning it was one of Astrolog's menu commands and */
  627. /* action was taken; 1, meaning it's the special end program command; or   */
  628. /* -1, meaning it's not a custom command and Windows can deal with it.     */
  629.  
  630. int NWmCommand(wCmd)
  631. WORD wCmd;
  632. {
  633.   char sz[cchSzDef];
  634.   DLGPROC dlgproc;
  635.   int i;
  636.   long l;
  637.   bool fGraphics, fT;
  638.  
  639.   wi.wCmd = wCmd;
  640.   fGraphics = us.fGraphics;
  641.   switch (wCmd) {
  642.  
  643.   /* File Menu */
  644.  
  645.   case cmdFileExit:
  646.     return 1;
  647.  
  648.   case cmdOpenChart:
  649.     wi.nDlgChart = 1;
  650.     DlgOpenChart();
  651.     break;
  652.  
  653.   case cmdOpenChart2:
  654.     wi.nDlgChart = 2;
  655.     DlgOpenChart();
  656.     break;
  657.  
  658.   case cmdSaveChart:
  659.   case cmdSavePositions:
  660.   case cmdSaveText:
  661.   case cmdSaveBitmap:
  662. #ifdef META
  663.   case cmdSavePicture:
  664. #endif
  665. #ifdef PS
  666.   case cmdSavePS:
  667. #endif
  668.   case cmdSaveSettings:
  669.   case cmdSaveWallTile:
  670.   case cmdSaveWallCenter:
  671.     DlgSaveChart();
  672.     break;
  673.  
  674.   case cmdPrint:
  675.     if (!DlgPrint())
  676.       PrintWarning("The printing was not completed successfully.");
  677.     break;
  678.  
  679.   case cmdPrintSetup:
  680.     l = prd.Flags;
  681.     prd.Flags |= PD_PRINTSETUP;
  682.     PrintDlg((LPPRINTDLG)&prd);
  683.     prd.Flags = l;
  684.     break;
  685.  
  686.   /* Edit Menu */
  687.  
  688.   case cmdCommand:
  689.     WiDoDialog(DlgCommand, dlgCommand);
  690.     break;
  691.  
  692.   case cmdColor:
  693.     WiDoDialog(DlgColor, dlgColor);
  694.     break;
  695.  
  696.   case cmdCopyText:
  697.     is.szFileScreen = szFileTemp;
  698.     us.fGraphics = fFalse;
  699.     wi.fRedraw = fTrue;
  700.     break;
  701.  
  702.   case cmdCopyBitmap:
  703. #ifdef META
  704.   case cmdCopyPicture:
  705. #endif
  706. #ifdef PS
  707.   case cmdCopyPS:
  708. #endif
  709.     if (us.fNoWrite)
  710.       break;
  711.     gi.szFileOut = szFileTemp;
  712.     gs.fBitmap = wi.wCmd == cmdCopyBitmap;
  713.     gs.fMeta = wi.wCmd == cmdCopyPicture;
  714.     gs.fPS = wi.wCmd == cmdCopyPS;
  715.     if (wCmd == cmdCopyBitmap)
  716.       gs.chBmpMode = 'B';
  717.     us.fGraphics = wi.fRedraw = fTrue;
  718.     break;
  719.  
  720.   /* View Menu */
  721.  
  722.   case cmdGraphics:
  723.     not(us.fGraphics);
  724.     wi.fRedraw = fTrue;
  725.     break;
  726.  
  727.   case cmdColoredText:
  728.     not(us.fAnsiColor); not(us.fAnsiChar);
  729.     WiCheckMenu(cmdColoredText, us.fAnsiColor);
  730.     us.fGraphics = fFalse;
  731.     wi.fRedraw = fTrue;
  732.     break;
  733.  
  734.   case cmdWinBuffer:
  735.     not(wi.fBuffer);
  736.     WiCheckMenu(cmdWinBuffer, wi.fBuffer);
  737.     break;
  738.  
  739.   case cmdWinRedraw:
  740.     if (wi.fNoUpdate)
  741.       wi.fNoUpdate = 2;
  742.     wi.fMenuAll = wi.fRedraw = fTrue;
  743.     break;
  744.  
  745.   case cmdWinClear:
  746.     fT = gs.fJetTrail;
  747.     gs.fJetTrail = fFalse;
  748.     wi.hdc = GetDC(wi.hwnd);
  749.     if (us.fGraphics)
  750.       DrawClearScreen();
  751.     else
  752.       TextClearScreen();
  753.     ReleaseDC(wi.hwnd, wi.hdc);
  754.     gs.fJetTrail = fT;
  755.     break;
  756.  
  757.   case cmdWinHourglass:
  758.     not(wi.fHourglass);
  759.     WiCheckMenu(cmdWinHourglass, wi.fHourglass);
  760.     break;
  761.  
  762.   case cmdChartResizesWindow:
  763.     not(wi.fChartWindow);
  764.     WiCheckMenu(cmdChartResizesWindow, wi.fChartWindow);
  765.     wi.fRedraw = fTrue;
  766.     break;
  767.  
  768.   case cmdWindowResizesChart:
  769.     not(wi.fWindowChart);
  770.     WiCheckMenu(cmdWindowResizesChart, wi.fWindowChart);
  771.     wi.fRedraw = fTrue;
  772.     break;
  773.  
  774.   case cmdSizeChartToWindow:
  775.     gs.xWin = wi.xClient;
  776.     gs.yWin = wi.yClient;
  777.     us.fGraphics = wi.fRedraw = fTrue;
  778.     break;
  779.  
  780.   case cmdSizeWindowToChart:
  781.     ResizeWindowToChart();
  782.     break;
  783.  
  784.   case cmdScrollPageUp:
  785.     PostMessage(wi.hwnd, WM_VSCROLL, SB_PAGEUP, 0);
  786.     break;
  787.  
  788.   case cmdScrollPageDown:
  789.     PostMessage(wi.hwnd, WM_VSCROLL, SB_PAGEDOWN, 0);
  790.     break;
  791.  
  792.   case cmdScrollHome:
  793.     PostMessage(wi.hwnd, WM_HSCROLL, SB_THUMBPOSITION, 0);
  794.     PostMessage(wi.hwnd, WM_VSCROLL, SB_THUMBPOSITION, 0);
  795.     break;
  796.  
  797.   case cmdScrollEnd:
  798.     PostMessage(wi.hwnd, WM_HSCROLL, SB_THUMBPOSITION, nScrollDiv);
  799.     PostMessage(wi.hwnd, WM_VSCROLL, SB_THUMBPOSITION, nScrollDiv);
  800.     break;
  801.  
  802. #ifdef INTERPRET
  803.   case cmdInterpret:
  804.     not(us.fInterpret);
  805.     WiCheckMenu(cmdInterpret, us.fInterpret);
  806.     us.fGraphics = fFalse;
  807.     wi.fRedraw = fTrue;
  808.     break;
  809. #endif
  810.  
  811.   case cmdSecond:
  812.     not(us.fSeconds);
  813.     is.fSeconds = us.fSeconds;
  814.     WiCheckMenu(cmdSecond, us.fSeconds);
  815.     wi.fRedraw = fTrue;
  816.     break;
  817.  
  818.   case cmdApplying:
  819.     not(us.fAppSep);
  820.     WiCheckMenu(cmdApplying, us.fAppSep);
  821.     wi.fRedraw = fTrue;
  822.     break;
  823.  
  824.   case cmdParallel:
  825.     not(us.fParallel);
  826.     WiCheckMenu(cmdParallel, us.fParallel);
  827.     wi.fRedraw = fTrue;
  828.     break;
  829.  
  830.   /* Info Menu */
  831.  
  832.   case cmdSetInfo:
  833.     wi.nDlgChart = 1;
  834.     WiDoDialog(DlgInfo, dlgInfo);
  835.     break;
  836.  
  837. #ifdef TIME
  838.   case cmdNow:
  839.     FInputData(szNowCore);
  840.     wi.fCast = fTrue;
  841.     break;
  842. #endif
  843.  
  844.   case cmdDefaultInfo:
  845.     WiDoDialog(DlgDefault, dlgDefault);
  846.     break;
  847.  
  848.   case cmdSetInfo2:
  849.     wi.nDlgChart = 2;
  850.     WiDoDialog(DlgInfo, dlgInfo);
  851.     break;
  852.  
  853.   case cmdSetInfoAll:
  854.     WiDoDialog(DlgInfoAll, dlgInfoAll);
  855.     break;
  856.  
  857.   case cmdRelNo:
  858.   case cmdRelComparison:
  859.     SetRel(us.nRel ? 0 : rcDual);
  860.     break;
  861.  
  862.   case cmdRelSynastry:
  863.     SetRel(rcSynastry);
  864.     break;
  865.  
  866.   case cmdRelComposite:
  867.     SetRel(rcComposite);
  868.     break;
  869.  
  870.   case cmdRelMidpoint:
  871.     SetRel(rcMidpoint);
  872.     break;
  873.  
  874.   case cmdRelDate:
  875.     SetRel(rcDifference);
  876.     gi.nMode = gWheel;
  877.     us.fGraphics = fFalse;
  878.     break;
  879.  
  880. #ifdef BIORHYTHM
  881.   case cmdRelBiorhythm:
  882.     SetRel(rcBiorhythm);
  883.     gi.nMode = gBiorhythm;
  884.     break;
  885. #endif
  886.  
  887.   case cmdRelTransit:
  888.     SetRel(rcTransit);
  889.     break;
  890.  
  891.   case cmdRelProgressed:
  892.     SetRel(rcProgress);
  893.     break;
  894.  
  895.   /* Settings Menu */
  896.  
  897.   case cmdSidereal:
  898.     not(us.fSidereal);
  899.     WiCheckMenu(cmdSidereal, us.fSidereal);
  900.     wi.fCast = fTrue;
  901.     break;
  902.  
  903.   case cmdHeliocentric:
  904.     not(us.objCenter);
  905.     WiCheckMenu(cmdHeliocentric, us.objCenter != oEar);
  906.     wi.fCast = fTrue;
  907.     break;
  908.  
  909.   case cmdHouse00:
  910.   case cmdHouse01:
  911.   case cmdHouse02:
  912.   case cmdHouse03:
  913.   case cmdHouse04:
  914.   case cmdHouse05:
  915.   case cmdHouse06:
  916.   case cmdHouse07:
  917.   case cmdHouse08:
  918.   case cmdHouse09:
  919.   case cmdHouse10:
  920.   case cmdHouse11:
  921.   case cmdHouse12:
  922.   case cmdHouse13:
  923.     WiCheckMenu(cmdHouse00 + us.nHouseSystem, fFalse);
  924.     us.nHouseSystem = (int)(wCmd - cmdHouse00);
  925.     WiCheckMenu(wCmd, fTrue);
  926.     wi.fCast = fTrue;
  927.     break;
  928.  
  929.   case cmdHouseSetSolar:
  930.     not(us.objOnAsc);
  931.     WiCheckMenu(cmdHouseSetSolar, us.objOnAsc);
  932.     wi.fCast = fTrue;
  933.     break;
  934.  
  935.   case cmdHouseSetDecan:
  936.     not(us.fDecan);
  937.     WiCheckMenu(cmdHouseSetDecan, us.fDecan);
  938.     wi.fCast = fTrue;
  939.     break;
  940.  
  941.   case cmdHouseSetFlip:
  942.     not(us.fFlip);
  943.     WiCheckMenu(cmdHouseSetFlip, us.fFlip);
  944.     wi.fCast = fTrue;
  945.     break;
  946.  
  947.   case cmdHouseSetGeodetic:
  948.     not(us.fGeodetic);
  949.     WiCheckMenu(cmdHouseSetGeodetic, us.fGeodetic);
  950.     wi.fCast = fTrue;
  951.     break;
  952.  
  953.   case cmdAspect:
  954.     WiDoDialog(DlgAspect, dlgAspect);
  955.     break;
  956.  
  957.   case cmdObject:
  958.     WiDoDialog(DlgObject, dlgObject);
  959.     break;
  960.  
  961.   case cmdObject2:
  962.     WiDoDialog(DlgObject2, dlgObject2);
  963.     break;
  964.  
  965.   case cmdRes:
  966.   case cmdResTransit:
  967.     WiDoDialog(DlgRestrict, dlgRestrict);
  968.     break;
  969.  
  970.   case cmdResMinor:
  971.     for (i = oChi; i <= oVes; i++)
  972.       not(ignore[i]);
  973.     for (i = oLil; i <= oEP; i++)
  974.       not(ignore[i]);
  975.     WiCheckMenu(cmdResMinor, !ignore[oChi]);
  976.     wi.fCast = fTrue;
  977.     break;
  978.  
  979.   case cmdResCusp:
  980.     not(us.fCusp);
  981.     for (i = cuspLo; i <= cuspHi; i++)
  982.       ignore[i] = !us.fCusp || !ignore[i];
  983.     WiCheckMenu(cmdResCusp, us.fCusp);
  984.     wi.fCast = fTrue;
  985.     break;
  986.  
  987.   case cmdResUranian:
  988.     not(us.fUranian);
  989.     for (i = uranLo; i <= uranHi; i++)
  990.       ignore[i] = !us.fUranian || !ignore[i];
  991.     WiCheckMenu(cmdResUranian, us.fUranian);
  992.     wi.fCast = fTrue;
  993.     break;
  994.  
  995.   case cmdResStar:
  996.     us.nStar = !us.nStar;
  997.     for (i = starLo; i <= starHi; i++)
  998.       ignore[i] = !us.nStar || !ignore[i];
  999.     WiCheckMenu(cmdResStar, us.nStar);
  1000.     wi.fCast = fTrue;
  1001.     break;
  1002.  
  1003.   case cmdStar:
  1004.     WiDoDialog(DlgStar, dlgStar);
  1005.     break;
  1006.  
  1007.   case cmdSettingMore:
  1008.     WiDoDialog(DlgSetting, dlgSetting);
  1009.     break;
  1010.  
  1011.   case cmdObscure:
  1012.     WiDoDialog(DlgObscure, dlgObscure);
  1013.     break;
  1014.  
  1015.   /* Chart Menu */
  1016.  
  1017.   case cmdChartList:
  1018.     wi.nMode = gWheel;
  1019.     break;
  1020.  
  1021.   case cmdChartWheel:
  1022.     wi.nMode = gHouse;
  1023.     break;
  1024.  
  1025.   case cmdChartGrid:
  1026.     wi.nMode = gGrid;
  1027.     break;
  1028.  
  1029.   case cmdChartAspect:
  1030.     wi.nMode = gAspect;
  1031.     us.fGraphics = fFalse;
  1032.     break;
  1033.  
  1034.   case cmdChartMidpoint:
  1035.     wi.nMode = gMidpoint;
  1036.     us.fGraphics = fFalse;
  1037.     break;
  1038.  
  1039.   case cmdChartHorizon:
  1040.     wi.nMode = gHorizon;
  1041.     break;
  1042.  
  1043.   case cmdChartOrbit:
  1044.     wi.nMode = gOrbit;
  1045.     break;
  1046.  
  1047.   case cmdChartSector:
  1048.     wi.nMode = gSector;
  1049.     break;
  1050.  
  1051.   case cmdChartCalendar:
  1052.     wi.nMode = gCalendar;
  1053.     break;
  1054.  
  1055.   case cmdChartInfluence:
  1056.     wi.nMode = gDisposit;
  1057.     break;
  1058.  
  1059.   case cmdChartAstroGraph:
  1060.     wi.nMode = gAstroGraph;
  1061.     break;
  1062.  
  1063.   case cmdChartEphemeris:
  1064.     wi.nMode = gEphemeris;
  1065.     break;
  1066.  
  1067. #ifdef ARABIC
  1068.   case cmdChartArabic:
  1069.     wi.nMode = gArabic;
  1070.     us.fGraphics = fFalse;
  1071.     break;
  1072. #endif
  1073.  
  1074.   case cmdChartRising:
  1075.     wi.nMode = gRising;
  1076.     us.fGraphics = fFalse;
  1077.     break;
  1078.  
  1079.   case cmdProgress:
  1080.     WiDoDialog(DlgProgress, dlgProgress);
  1081.     break;
  1082.  
  1083.   case cmdTransit:
  1084.     WiDoDialog(DlgTransit, dlgTransit);
  1085.     break;
  1086.  
  1087.   case cmdChartSettings:
  1088.     WiDoDialog(DlgChart, dlgChart);
  1089.     break;
  1090.  
  1091.   /* Graphics Menu */
  1092.  
  1093.   case cmdChartMap:
  1094.     wi.nMode = gWorldMap;
  1095.     us.fGraphics = wi.fRedraw = fTrue;
  1096.     break;
  1097.  
  1098.   case cmdChartGlobe:
  1099.     wi.nMode = gGlobe;
  1100.     us.fGraphics = wi.fRedraw = fTrue;
  1101.     break;
  1102.  
  1103.   case cmdChartPolar:
  1104.     wi.nMode = gPolar;
  1105.     us.fGraphics = wi.fRedraw = fTrue;
  1106.     break;
  1107.  
  1108. #ifdef CONSTEL
  1109.   case cmdConstellation:
  1110.     if (!fMap && gi.nMode != gGlobe && gi.nMode != gPolar)
  1111.       wi.nMode = gWorldMap;
  1112.     not(gs.fConstel);
  1113.     WiCheckMenu(cmdConstellation, gs.fConstel);
  1114.     us.fGraphics = wi.fRedraw = fTrue;
  1115.     break;
  1116. #endif
  1117.  
  1118.   case cmdGraphicsReverse:
  1119.     not(gs.fInverse);
  1120.     WiCheckMenu(cmdGraphicsReverse, gs.fInverse);
  1121.     us.fGraphics = wi.fRedraw = fTrue;
  1122.     break;
  1123.  
  1124.   case cmdGraphicsMonochrome:
  1125.     not(gs.fColor);
  1126.     WiCheckMenu(cmdGraphicsMonochrome, !gs.fColor);
  1127.     us.fGraphics = wi.fRedraw = fTrue;
  1128.     break;
  1129.  
  1130.   case cmdGraphicsBorder:
  1131.     not(gs.fBorder);
  1132.     WiCheckMenu(cmdGraphicsBorder, gs.fBorder);
  1133.     us.fGraphics = wi.fRedraw = fTrue;
  1134.     break;
  1135.  
  1136.   case cmdGraphicsText:
  1137.     not(gs.fText);
  1138.     WiCheckMenu(cmdGraphicsText, gs.fText);
  1139.     us.fGraphics = wi.fRedraw = fTrue;
  1140.     break;
  1141.  
  1142.   case cmdGraphicsSidebar:
  1143.     not(us.fVelocity);
  1144.     if (!us.fVelocity) {
  1145.       gs.fText = fTrue;
  1146.       WiCheckMenu(cmdGraphicsText, fTrue);
  1147.     }
  1148.     WiCheckMenu(cmdGraphicsSidebar, !us.fVelocity);
  1149.     wi.nMode = gWheel;
  1150.     us.fGraphics = wi.fRedraw = fTrue;
  1151.     break;
  1152.  
  1153.   case cmdGraphicsLabel:
  1154.     not(gs.fLabel);
  1155.     WiCheckMenu(cmdGraphicsLabel, gs.fLabel);
  1156.     us.fGraphics = wi.fRedraw = fTrue;
  1157.     break;
  1158.  
  1159.   case cmdGraphicsSquare:
  1160.     SquareX(&gs.xWin, &gs.yWin, fTrue);
  1161.     ResizeWindowToChart();
  1162.     us.fGraphics = wi.fRedraw = fTrue;
  1163.     break;
  1164.  
  1165.   case cmdScale1:
  1166.   case cmdScale2:
  1167.   case cmdScale3:
  1168.   case cmdScale4:
  1169.     WiCheckMenu(cmdScale1 + gs.nScale/100 - 1, fFalse);
  1170.     gs.nScale = (int)(wCmd - cmdScale1) + 1;
  1171.     gs.nScale *= 100;
  1172.     WiCheckMenu(wCmd, fTrue);
  1173.     wi.fRedraw = fTrue;
  1174.     break;
  1175.  
  1176.   case cmdScaleDecrease:
  1177.     if (gs.nScale > 100) {
  1178.       WiCheckMenu(cmdScale1 + gs.nScale/100 - 1, fFalse);
  1179.       gs.nScale -= 100;
  1180. LScale:
  1181.       WiCheckMenu(cmdScale1 + gs.nScale/100 - 1, fTrue);
  1182.       wi.fRedraw = fTrue;
  1183.     }
  1184.     break;
  1185.  
  1186.   case cmdScaleIncrease:
  1187.     if (gs.nScale < MAXSCALE) {
  1188.       WiCheckMenu(cmdScale1 + gs.nScale/100 - 1, fFalse);
  1189.       gs.nScale += 100;
  1190.       goto LScale;
  1191.     }
  1192.     break;
  1193.  
  1194.   case cmdTiltZero:
  1195.     if (gi.nMode != gGlobe)
  1196.       wi.nMode = gGlobe;
  1197.     if (gs.rTilt != 0.0) {
  1198.       gs.rTilt = 0.0;
  1199.       wi.fRedraw = fTrue;
  1200.     }
  1201.     us.fGraphics = fTrue;
  1202.     break;
  1203.  
  1204.   case cmdTiltDecrease:
  1205.     if (gi.nMode != gGlobe)
  1206.       wi.nMode = gGlobe;
  1207.     if (gs.rTilt > -rDegQuad) {
  1208.       gs.rTilt = gs.rTilt > -rDegQuad ? gs.rTilt-TILTSTEP : -rDegQuad;
  1209.       wi.fRedraw = fTrue;
  1210.     }
  1211.     us.fGraphics = fTrue;
  1212.     break;
  1213.  
  1214.   case cmdTiltIncrease:
  1215.     if (gi.nMode != gGlobe)
  1216.       wi.nMode = gGlobe;
  1217.     if (gs.rTilt < rDegQuad) {
  1218.       gs.rTilt = gs.rTilt < rDegQuad ? gs.rTilt+TILTSTEP : rDegQuad;
  1219.       wi.fRedraw = fTrue;
  1220.     }
  1221.     us.fGraphics = fTrue;
  1222.     break;
  1223.  
  1224.   case cmdGraphicsModify:
  1225.     not(gs.fAlt);
  1226.     WiCheckMenu(cmdGraphicsModify, gs.fAlt);
  1227.     us.fGraphics = wi.fRedraw = fTrue;
  1228.     break;
  1229.  
  1230.   case cmdChartModify:
  1231.     not(us.fPrimeVert);
  1232.     not(us.fCalendarYear);
  1233.     not(us.nEphemYears);
  1234.     not(gs.fMollewide);
  1235.     gi.nMode = (gi.nMode == gWheel ? gHouse :
  1236.       (gi.nMode == gHouse ? gWheel : gi.nMode));
  1237.     us.fGraphics = wi.fRedraw = fTrue;
  1238.     break;
  1239.  
  1240.   case cmdPen00:
  1241.   case cmdPen01:
  1242.   case cmdPen02:
  1243.   case cmdPen03:
  1244.   case cmdPen04:
  1245.   case cmdPen05:
  1246.   case cmdPen06:
  1247.   case cmdPen07:
  1248.   case cmdPen08:
  1249.   case cmdPen09:
  1250.   case cmdPen10:
  1251.   case cmdPen11:
  1252.   case cmdPen12:
  1253.   case cmdPen13:
  1254.   case cmdPen14:
  1255.   case cmdPen15:
  1256.     WiCheckMenu(cmdPen00 + wi.kiPen, fFalse);
  1257.     wi.kiPen = (int)(wCmd - cmdPen00);
  1258.     WiCheckMenu(wCmd, fTrue);
  1259.     break;
  1260.  
  1261.   case cmdSettingGraphics:
  1262.     WiDoDialog(DlgGraphics, dlgGraphics);
  1263.     break;
  1264.  
  1265.   /* Animate Menu */
  1266.  
  1267.   case cmdAnimateNo:
  1268.   case cmdAnimateNow:
  1269.     WiCheckMenu(cmdAnimateNo + gs.nAnim, fFalse);
  1270.     if (gs.nAnim)
  1271.       gs.nAnim = 0;
  1272.     else {
  1273.       gs.nAnim = 10;
  1274.       WiCheckMenu(cmdWinBuffer, fTrue);
  1275.       wi.fBuffer = fTrue;
  1276.     }
  1277.     WiCheckMenu(cmdAnimateNo + gs.nAnim, fTrue);
  1278.     wi.fRedraw = fTrue;
  1279.     break;
  1280.  
  1281.   case cmdAnimateS1:
  1282.   case cmdAnimateS2:
  1283.   case cmdAnimateS3:
  1284.   case cmdAnimateS4:
  1285.   case cmdAnimateS5:
  1286.   case cmdAnimateS6:
  1287.   case cmdAnimateS7:
  1288.   case cmdAnimateS8:
  1289.   case cmdAnimateS9:
  1290.     WiCheckMenu(cmdAnimateNo + gs.nAnim, fFalse);
  1291.     gs.nAnim = (int)(wCmd - cmdAnimateS1) + 1;
  1292.     WiCheckMenu(wCmd, fTrue);
  1293.     WiCheckMenu(cmdWinBuffer, fTrue);
  1294.     wi.fBuffer = wi.fRedraw = fTrue;
  1295.     break;
  1296.  
  1297.   case cmdAnimateF1:
  1298.   case cmdAnimateF2:
  1299.   case cmdAnimateF3:
  1300.   case cmdAnimateF4:
  1301.   case cmdAnimateF5:
  1302.   case cmdAnimateF6:
  1303.   case cmdAnimateF7:
  1304.   case cmdAnimateF8:
  1305.   case cmdAnimateF9:
  1306.     WiCheckMenu(cmdAnimateF1 + abs(wi.nDir) - 1, fFalse);
  1307.     wi.nDir = (wi.nDir > 0 ? 1 : -1)*(int)(wCmd - cmdAnimateF1) + 1;
  1308.     WiCheckMenu(wCmd, fTrue);
  1309.     break;
  1310.  
  1311.   case cmdAnimateReverse:
  1312.     neg(wi.nDir);
  1313.     WiCheckMenu(cmdAnimateReverse, wi.nDir < 0);
  1314.     if (gs.nAnim == 0) {
  1315.       gs.nAnim = 10;
  1316.       WiCheckMenu(cmdWinBuffer, fTrue);
  1317.       WiCheckMenu(cmdAnimateNo, fFalse);
  1318.       WiCheckMenu(cmdAnimateNow, fTrue);
  1319.       wi.fBuffer = fTrue;
  1320.     }
  1321.     wi.fRedraw = fTrue;
  1322.     break;
  1323.  
  1324.   case cmdAnimatePause:
  1325.     not(wi.fPause);
  1326.     WiCheckMenu(cmdAnimatePause, wi.fPause);
  1327.     break;
  1328.  
  1329.   case cmdTimedExposure:
  1330.     not(gs.fJetTrail);
  1331.     WiCheckMenu(cmdTimedExposure, gs.fJetTrail);
  1332.     break;
  1333.  
  1334.   case cmdStepForward:
  1335.     Animate(gs.nAnim, abs(wi.nDir));
  1336.     wi.fCast = fTrue;
  1337.     break;
  1338.  
  1339.   case cmdStepBackward:
  1340.     Animate(gs.nAnim, -abs(wi.nDir));
  1341.     wi.fCast = fTrue;
  1342.     break;
  1343.  
  1344.   case cmdStore:
  1345.     ciSave = ciMain;
  1346.     break;
  1347.  
  1348.   case cmdRecall:
  1349.     ciMain = ciSave;
  1350.     wi.fCast = fTrue;
  1351.     break;
  1352.  
  1353.   /* Help Menu */
  1354.  
  1355.   case cmdDocDefault:
  1356.     WinExec("NOTEPAD ASTROLOG.DAT", SW_SHOW);
  1357.     break;
  1358.  
  1359.   case cmdDocSummary:
  1360.     WinExec("NOTEPAD FILE_ID.DIZ", SW_SHOW);
  1361.     break;
  1362.  
  1363.   case cmdDocReadme:
  1364.     WinExec("NOTEPAD README.530", SW_SHOW);
  1365.     break;
  1366.  
  1367.   case cmdDocUpdate:
  1368.     WinExec("NOTEPAD UPDATE.530", SW_SHOW);
  1369.     break;
  1370.  
  1371.   case cmdDocHelpfile:
  1372.     WinExec("WRITE HELPFILE.530", SW_SHOW);
  1373.     break;
  1374.  
  1375.   case cmdHelpSign:
  1376.     wi.nMode = gSign;
  1377.     us.fGraphics = fFalse;
  1378.     break;
  1379.  
  1380.   case cmdHelpObject:
  1381.     wi.nMode = gObject;
  1382.     us.fGraphics = fFalse;
  1383.     break;
  1384.  
  1385.   case cmdHelpAspect:
  1386.     wi.nMode = gHelpAsp;
  1387.     us.fGraphics = fFalse;
  1388.     break;
  1389.  
  1390. #ifdef CONSTEL
  1391.   case cmdHelpConstellation:
  1392.     wi.nMode = gConstel;
  1393.     us.fGraphics = fFalse;
  1394.     break;
  1395. #endif
  1396.  
  1397.   case cmdHelpPlanetInfo:
  1398.     wi.nMode = gPlanet;
  1399.     us.fGraphics = fFalse;
  1400.     break;
  1401.  
  1402. #ifdef INTERPRET
  1403.   case cmdHelpMeaning:
  1404.     wi.nMode = gMeaning;
  1405.     us.fGraphics = fFalse;
  1406.     break;
  1407. #endif
  1408.  
  1409.   case cmdHelpSwitch:
  1410.     wi.nMode = gSwitch;
  1411.     us.fGraphics = fFalse;
  1412.     break;
  1413.  
  1414.   case cmdHelpObscure:
  1415.     wi.nMode = gObscure;
  1416.     us.fGraphics = fFalse;
  1417.     break;
  1418.  
  1419.   case cmdHelpKeystroke:
  1420.     wi.nMode = gKeystroke;
  1421.     us.fGraphics = fFalse;
  1422.     break;
  1423.  
  1424.   case cmdHelpCredit:
  1425.     wi.nMode = gCredit;
  1426.     us.fGraphics = fFalse;
  1427.     break;
  1428.  
  1429.   case cmdHelpAbout:
  1430.     WiDoDialog(DlgAbout, dlgAbout);
  1431.     break;
  1432.  
  1433.   default:
  1434.     if (FBetween(wCmd, cmdMacro01, cmdMacro48)) {
  1435.       i = (int)(wCmd - cmdMacro01);
  1436.       if (szMacro[i]) {
  1437.         FProcessCommandLine(szMacro[i]);
  1438.         wi.fCast = wi.fMenuAll = fTrue;
  1439.       } else {
  1440.         sprintf(sz, "Macro number %d is not defined.", i+1);
  1441.         PrintWarning(sz);
  1442.       }
  1443.       break;
  1444.     }
  1445.     return -1;
  1446.   }
  1447.  
  1448.   if (us.fNoGraphics)
  1449.     us.fGraphics = fFalse;
  1450.   if (us.fGraphics != fGraphics)
  1451.     WiCheckMenu(cmdGraphics, us.fGraphics);
  1452.   return 0;
  1453. }
  1454.  
  1455.  
  1456. /* For each menu command that can have a check mark by it, determine its   */
  1457. /* state and set or clear appropriately. This is called when the program   */
  1458. /* is first started, and after commands that may change many settings that */
  1459. /* can't be kept track of, such as running macro commands or script files. */
  1460.  
  1461. void API RedoMenu()
  1462. {
  1463.   WORD cmd;
  1464.  
  1465.   CheckMenu(cmdGraphics, us.fGraphics);
  1466.   CheckMenu(cmdColoredText, us.fAnsiColor);
  1467.   CheckMenu(cmdWinBuffer, wi.fBuffer);
  1468.   CheckMenu(cmdWinHourglass, wi.fHourglass);
  1469.   CheckMenu(cmdChartResizesWindow, wi.fChartWindow);
  1470.   CheckMenu(cmdWindowResizesChart, wi.fWindowChart);
  1471. #ifdef INTERPRET
  1472.   CheckMenu(cmdInterpret, us.fInterpret);
  1473. #endif
  1474.   CheckMenu(cmdSecond, us.fSeconds);
  1475.   CheckMenu(cmdApplying, us.fAppSep);
  1476.   CheckMenu(cmdParallel, us.fParallel);
  1477.   for (cmd = cmdRelNo; cmd <= cmdRelProgressed; cmd++)
  1478.     CheckMenu(cmd, fFalse);
  1479.   CheckMenu(WCmdFromRc(us.nRel), fTrue);
  1480.   CheckMenu(cmdSidereal, us.fSidereal);
  1481.   CheckMenu(cmdHeliocentric, us.objCenter != oEar);
  1482.   for (cmd = cmdHouse00; cmd <= cmdHouse13; cmd++)
  1483.     CheckMenu(cmd, fFalse);
  1484.   CheckMenu(cmdHouse00 + us.nHouseSystem, fTrue);
  1485.   CheckMenu(cmdHouseSetSolar, us.objOnAsc);
  1486.   CheckMenu(cmdHouseSetDecan, us.fDecan);
  1487.   CheckMenu(cmdHouseSetFlip, us.fFlip);
  1488.   CheckMenu(cmdHouseSetGeodetic, us.fGeodetic);
  1489.   CheckMenu(cmdResMinor, !ignore[oChi]);
  1490.   CheckMenu(cmdResCusp, us.fCusp);
  1491.   CheckMenu(cmdResUranian, us.fUranian);
  1492.   CheckMenu(cmdResStar, us.nStar);
  1493. #ifdef CONSTEL
  1494.   CheckMenu(cmdConstellation, gs.fConstel);
  1495. #endif
  1496.   CheckMenu(cmdGraphicsReverse, gs.fInverse);
  1497.   CheckMenu(cmdGraphicsMonochrome, !gs.fColor);
  1498.   CheckMenu(cmdGraphicsBorder, gs.fBorder);
  1499.   CheckMenu(cmdGraphicsText, gs.fText);
  1500.   CheckMenu(cmdGraphicsSidebar, !us.fVelocity);
  1501.   CheckMenu(cmdGraphicsLabel, gs.fLabel);
  1502.   for (cmd = cmdScale1; cmd <= cmdScale4; cmd++)
  1503.     CheckMenu(cmd, fFalse);
  1504.   CheckMenu(cmdScale1 + gs.nScale/100 - 1, fTrue);
  1505.   CheckMenu(cmdGraphicsModify, gs.fAlt);
  1506.   for (cmd = cmdPen00; cmd <= cmdPen15; cmd++)
  1507.     CheckMenu(cmd, fFalse);
  1508.   CheckMenu(cmdPen00 + wi.kiPen, fTrue);
  1509.   CheckMenu(cmdAnimateNow, fFalse);
  1510.   for (cmd = cmdAnimateNo; cmd <= cmdAnimateS9; cmd++)
  1511.     CheckMenu(cmd, fFalse);
  1512.   CheckMenu(cmdAnimateNo + gs.nAnim, fTrue);
  1513.   for (cmd = cmdAnimateF1; cmd <= cmdAnimateF9; cmd++)
  1514.     CheckMenu(cmd, fFalse);
  1515.   CheckMenu(cmdAnimateF1 + abs(wi.nDir) - 1, fTrue);
  1516.   CheckMenu(cmdAnimateReverse, wi.nDir < 0);
  1517.   CheckMenu(cmdAnimatePause, wi.fPause);
  1518.   CheckMenu(cmdTimedExposure, gs.fJetTrail);
  1519.   wi.fMenuAll = fFalse;
  1520. }
  1521.  
  1522.  
  1523. /* This important routine is the bottleneck to redraw the window and call */
  1524. /* into the program to draw or do action with a particular chart type.    */
  1525.  
  1526. bool API FRedraw(void)
  1527. {
  1528.   /* Local variables used in drawing on the screen. */
  1529.   PAINTSTRUCT ps;
  1530.   HDC hdcWin;
  1531.   HCURSOR hcurOld;
  1532.   HBITMAP hbmp, hbmpOld;
  1533.   HFONT hfontOld;
  1534.   int nScrollRow, i;
  1535.  
  1536.   /* Local variables used for copying to the Windows clipboard. */
  1537.   HFILE hfile;
  1538.   LONG lSize, l;
  1539.   HGLOBAL hglobal, hmfp;
  1540.   byte HPTR *hpb;
  1541.   METAFILEPICT mfp;
  1542.  
  1543.   if (wi.fHourglass)
  1544.     hcurOld = SetCursor(LoadCursor((HINSTANCE)NULL, IDC_WAIT));
  1545.   ClearB((lpbyte)&ps, sizeof(PAINTSTRUCT));
  1546.   if (wi.hdcPrint != hdcNil)
  1547.     wi.hdc = wi.hdcPrint;
  1548.   else {
  1549.     hdcWin = BeginPaint(wi.hwnd, &ps);
  1550.     if (wi.fBuffer) {
  1551.       wi.hdc = CreateCompatibleDC(hdcWin);
  1552.       hbmp = CreateCompatibleBitmap(hdcWin, wi.xClient, wi.yClient);
  1553.       hbmpOld = SelectObject(wi.hdc, hbmp);
  1554.       if (gs.fJetTrail)
  1555.         BitBlt(wi.hdc, 0, 0, wi.xClient, wi.yClient, hdcWin, 0, 0, SRCCOPY);
  1556.     } else
  1557.       wi.hdc = hdcWin;
  1558.   }
  1559.  
  1560.   if (us.fGraphics) {
  1561.     /* Set up a graphics chart. */
  1562.     if (wi.fWindowChart && wi.hdcPrint == hdcNil) {
  1563.       gs.xWin = wi.xClient; gs.yWin = wi.yClient;
  1564.     }
  1565.     gi.nScale = gs.nScale/100;
  1566.     gi.kiCur = -1;
  1567.   } else {
  1568.     /* Set up a text chart. */
  1569.     SetWindowOrg(wi.hdc, 0, 0);
  1570.     SetWindowExt(wi.hdc, wi.xClient, wi.yClient);
  1571.     SetBkMode(wi.hdc, TRANSPARENT);
  1572.     if (wi.hdcPrint == hdcNil)
  1573.       TextClearScreen();
  1574.     i = gs.nScale/100;
  1575.     wi.xChar = i < 2 ? 6 : (i < 3 ? 8 : (i < 4 ? 10 : 12));
  1576.     wi.yChar = i < 2 ? 8 : (i < 3 ? 12 : (i < 4 ? 18 : 16));
  1577.     wi.hfont = CreateFont(wi.yChar /*nHeight*/, wi.xChar /*nWidth*/,
  1578.       0 /*nEscapement*/, 0 /*nOrientation*/, FW_DONTCARE,
  1579.       0 /*fbItalic*/, 0 /*fbUnderline*/, 0 /*fbStrikeOut*/,
  1580.       DEFAULT_CHARSET, OUT_CHARACTER_PRECIS, CLIP_DEFAULT_PRECIS,
  1581.       DRAFT_QUALITY, FIXED_PITCH | FF_DONTCARE, "Terminal");
  1582.     hfontOld = SelectObject(wi.hdc, wi.hfont);
  1583.     /* If printing, set the number of text rows per page. */
  1584.     if (wi.hdcPrint != hdcNil) {
  1585.       nScrollRow = us.nScrollRow;
  1586.       us.nScrollRow = wi.yClient / wi.yChar;
  1587.     }
  1588.   }
  1589.  
  1590.   Action();    /* Actually go and create the chart here. */
  1591.  
  1592.   /* Cleanup and copy from the buffer to the screen if need be. */
  1593.  
  1594.   if (!us.fGraphics) {
  1595.     if (wi.hdcPrint != hdcNil)
  1596.       us.nScrollRow = nScrollRow;
  1597.     SelectObject(wi.hdc, hfontOld);
  1598.     DeleteObject(wi.hfont);
  1599.   }
  1600.   if (wi.hdcPrint == hdcNil) {
  1601.     if (wi.fBuffer) {
  1602.       BitBlt(hdcWin, 0, 0, wi.xClient, wi.yClient, wi.hdc, 0, 0, SRCCOPY);
  1603.       SelectObject(wi.hdc, hbmpOld);
  1604.       DeleteObject(hbmp);
  1605.       DeleteDC(wi.hdc);
  1606.     }
  1607.     EndPaint(wi.hwnd, &ps);
  1608.   }
  1609.   if (wi.fHourglass)
  1610.     SetCursor(hcurOld);
  1611.  
  1612.   /* If all text was scrolled off the top of the screen, scroll up. */
  1613.  
  1614.   if (!us.fGraphics && is.S == stdout && is.cchRow - wi.yScroll * 10 < 0)
  1615.     PostMessage(wi.hwnd, WM_VSCROLL, SB_THUMBPOSITION, is.cchRow / 10 - 2);
  1616.  
  1617.   /* Sometimes creating a chart means saving it to a file instead of     */
  1618.   /* drawing it on screen. If we were in file mode, cleanup things here. */
  1619.  
  1620.   if (is.szFileScreen != NULL || gs.fBitmap || gs.fMeta || gs.fPS) {
  1621.     is.szFileScreen = NULL;
  1622.     if (gs.fMeta) {
  1623.       gs.xWin /= METAMUL; gs.yWin /= METAMUL; gs.nScale /= METAMUL;
  1624.     } else if (gs.fPS) {
  1625.       gs.xWin /= PSMUL; gs.yWin /= PSMUL; gs.nScale /= PSMUL;
  1626.     }
  1627.     gs.fBitmap = gs.fMeta = gs.fPS = fFalse;
  1628.  
  1629.     /* To copy charts to the clipboard, Astrolog saves the chart to a temp */
  1630.     /* file, then copies the contents of that file to the clipboard.       */
  1631.  
  1632.     if (wi.wCmd == cmdCopyText || wi.wCmd == cmdCopyBitmap ||
  1633.       wi.wCmd == cmdCopyPicture || wi.wCmd == cmdCopyPS) {
  1634.       hfile = _lopen(szFileTemp, READ);
  1635.       if (hfile == HFILE_ERROR)
  1636.         return fFalse;
  1637.       lSize = _llseek(hfile, 0, 2);
  1638.       /* For bitmap and metafile charts, skip over the file header bytes. */
  1639.       l = wi.wCmd == cmdCopyBitmap ? sizeof(BITMAPFILEHEADER) :
  1640.         (wi.wCmd == cmdCopyPicture ? 22 : 0);
  1641.       hglobal = GlobalAlloc(GMEM_MOVEABLE, lSize - l);
  1642.       if (hglobal == (HGLOBAL)NULL)
  1643.         return fFalse;
  1644.       hpb = GlobalLock(hglobal);
  1645.       _llseek(hfile, l, 0);
  1646.       _hread(hfile, hpb, lSize - l);
  1647.       _lclose(hfile);
  1648.       GlobalUnlock(hglobal);
  1649.       if (!OpenClipboard(wi.hwnd))
  1650.         return fFalse;
  1651.       EmptyClipboard();
  1652.       if (wi.wCmd == cmdCopyText || wi.wCmd == cmdCopyPS)
  1653.         SetClipboardData(CF_TEXT, hglobal);
  1654.       else if (wi.wCmd == cmdCopyBitmap)
  1655.         SetClipboardData(CF_DIB, hglobal);
  1656.       else {
  1657.         mfp.mm = MM_ANISOTROPIC;  /* For metafiles a special structure  */
  1658.         mfp.xExt = -gs.xWin;      /* with a pointer to the picture data */
  1659.         mfp.yExt = -gs.yWin;      /* needs to be allocated and used.    */
  1660.         mfp.hMF = hglobal;
  1661.         hmfp = GlobalAlloc(GMEM_MOVEABLE, sizeof(METAFILEPICT));
  1662.         if (hmfp == (HGLOBAL)NULL)
  1663.           return fFalse;
  1664.         hpb = GlobalLock(hmfp);
  1665.         *(METAFILEPICT FAR *)hpb = mfp;
  1666.         GlobalUnlock(hmfp);
  1667.         SetClipboardData(CF_METAFILEPICT, hmfp);
  1668.       }
  1669.       CloseClipboard();
  1670.       _unlink(szFileTemp);
  1671.       wi.wCmd = 0;
  1672.     }
  1673.     ProcessState();
  1674.   }
  1675.  
  1676.   wi.fRedraw = fFalse;
  1677.   if (wi.fNoUpdate)
  1678.     wi.fNoUpdate = fTrue;
  1679.   return fTrue;
  1680. }
  1681. #endif /* WIN */
  1682.  
  1683. /* wdriver.c */
  1684.